package HashMap.Nodo.Operaciones;

import HashMap.Nodo.Nodo;
import HashMap.Nodo.Operacion;
import HashMap.Nodo.TipoBasicoDeDatos;
import java.util.LinkedList;
import java.util.List;

public class OperacionesCondicionalesYBucles implements Operacion {

    private Nodo nodo;
    private List<Operacion> operacionesBucle;
    private LinkedList<Operacion> operacionesElse;

    public OperacionesCondicionalesYBucles(Nodo nodoCondicion, LinkedList<Operacion> operacionesBucleOCondicional, String operacion) {
        if (cumpleCondiciones()) {
            this.nodo = nodoCondicion;
            this.nodo.setOperacion(operacion);
            this.operacionesBucle = operacionesBucleOCondicional;
        } else {
            throw new UnsupportedOperationException("Fallo en las condiciones del condicional...");
        }
    }

    public OperacionesCondicionalesYBucles(Nodo nodoCondicion, List<Operacion> operacionesBucleOCondicional, LinkedList<Operacion> operacionesBucleOCondicional2, String operacion) {
        if (cumpleCondiciones()) {
            this.nodo = nodoCondicion;
            this.nodo.setOperacion(operacion);
            this.operacionesBucle = operacionesBucleOCondicional;
            this.operacionesElse = operacionesBucleOCondicional2;
        } else {
            throw new UnsupportedOperationException("Fallo en las condiciones del condicional...");
        }
    }

    @Override
    public int getLongitud() {
        throw new UnsupportedOperationException("Función no soportada");
    }

    @Override
    public String generarCodigoNASM() {
        switch (nodo.getOperacion()) {
            case "IF":
                return generarCodigoNASMIF();
            case "ELSE":
                return generarCodigoNASMIFELSE();
            case "WHILE":
                return generarCodigoNASMWHILE();
            case "FOR":
                return generarCodigoNASMFOR();
            default:
                return null;
        }
    }

    @Override
    public Nodo generarNodo(String tokenOperacion) {
        throw new IllegalArgumentException("Funcion No Soportada");
    }

    private boolean cumpleCondiciones() {
        if (nodo.getTipoBasicoDeDatos() == TipoBasicoDeDatos.BOOLEAN && nodo.getNivelDeIndireccion() < 2) {
            return true;
        }
        return false;
    }

    private String generarCodigoNASMIF() {
        String codigo = "mov [aux], [" + nodo.getNombre() + "]\n"
                + "jfalse finIf\n";
        for (Operacion sent : operacionesBucle) {
            codigo += sent.generarCodigoNASM();
            codigo += "\n";
        }
        codigo += "finIf: \n";
        return codigo;
    }

    private String generarCodigoNASMIFELSE() {
        String codigo = "mov [aux], [" + nodo.getNombre() + "]\n"
                + "jfalse else\n";
        for (Operacion sentencia : operacionesBucle) {
            codigo += sentencia.generarCodigoNASM();
            codigo += "\n";
        }
        codigo += "jmp finIf\n else: \n";
        for (Operacion sentencia : operacionesElse) {
            codigo += sentencia.generarCodigoNASM();
            codigo += "\n";
        }
        codigo += "finIf";
        return null;
    }

    private String generarCodigoNASMWHILE() {
        String bucle = "Bucle:\n"
                + "mov [aux], [" + nodo.getNombre() + "]\n"
                + "jfalse finBucle";
        for (Operacion sentencia : operacionesBucle) {
            bucle += sentencia.generarCodigoNASM();
            bucle += "\n";
        }
        bucle += "finBucle";
        return bucle;
    }

    private String generarCodigoNASMFOR() {
        String definitivo = "mov [" + nodo.getNombre() + "], [" + nodo.getNombre() + "]\n"
                + "inicioBucle:"
                + "mov [aux], [" + nodo.getNombre() + "]\n"
                + "jfalse finBucle\n";
        for (Operacion sentencia : operacionesBucle) {
            definitivo += sentencia.generarCodigoNASM();
            definitivo += "\n";
        }
        definitivo += "jmp inicioBucle\nfinBucle:";
        return definitivo;
    }
}
